home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume22 / gawk2.11 / part15 < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  50.6 KB

  1. Subject:  v22i101:  GNU AWK, version 2.11, Part15/16
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: cc05cd37 b9632938 7accf7ff 9b18de3a
  5.  
  6. Submitted-by: "Arnold D. Robbins" <arnold@unix.cc.emory.edu>
  7. Posting-number: Volume 22, Issue 101
  8. Archive-name: gawk2.11/part15
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  ./CHANGES ./Makefile ./alloca.s ./field.c
  17. #   ./gawk.texinfo.07 ./node.c
  18. # Wrapped by rsalz@litchi.bbn.com on Wed Jun  6 12:25:01 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. echo If this archive is complete, you will see the following message:
  21. echo '          "shar: End of archive 15 (of 16)."'
  22. if test -f './CHANGES' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'./CHANGES'\"
  24. else
  25.   echo shar: Extracting \"'./CHANGES'\" \(6927 characters\)
  26.   sed "s/^X//" >'./CHANGES' <<'END_OF_FILE'
  27. XChanges from 2.11beta to 2.11.1 (production)
  28. X--------------------------------------------
  29. X
  30. XWent from "beta" to production status!!!
  31. X
  32. XNow flushes stdout before closing pipes or redirected files to
  33. Xsynchonize output.
  34. X
  35. XMS-DOS changes added in.
  36. X
  37. XSignal handler return type parameterized in Makefile and awk.h and
  38. Xsome lint removed.  debug.c cleaned up.
  39. X
  40. XFixed FS splitting to never match null strings, per book.
  41. X
  42. XCorrection to the manual's description of FS.
  43. X
  44. XSome compilers break on char *foo = "string" + 4 so fixed version.sh and
  45. Xmain.c.
  46. X
  47. XChanges from 2.10beta to 2.11beta
  48. X---------------------------------
  49. X
  50. XThis release fixes all reported bugs that we could reproduce.  Probably
  51. Xsome of the changes are not documented here.
  52. X
  53. XThe next release will probably not be a beta release!
  54. X
  55. XThe most important change is the addition of the -nostalgia option. :-)
  56. X
  57. XThe documentation has been improved and brought up-to-date.
  58. X
  59. XThere has been a lot of general cleaning up of the code that is not otherwise
  60. Xdocumented here.  There has been a movement toward using standard-conforming
  61. Xlibrary routines and providing them (in missing.d) for systems lacking them.
  62. XImproved (hopefully) configuration through Makfile modifications and missing.c.
  63. XIn particular, straightened out confusion over vprintf #defines, declarations
  64. Xetc.
  65. X
  66. XDeleted RCS log comments from source, to reduce source size by about one third.
  67. XMost of them were horribly out-of-date, anyway.
  68. X
  69. XRenamed source files to reflect (for the most part) their contents.
  70. X
  71. XMore and improved error messages.  Cleanup and fixes to yyerror().
  72. XString constants are not altered in input buffer, so error messages come out 
  73. Xbetter.  Fixed usage message.  Make use of ANSI C strerror() function
  74. X(provided).
  75. X
  76. XPlugged many more memory leaks.  The memory consumption is now quite
  77. Xreasonable over a wide range of programs.
  78. X
  79. XUses volatile declaration if STDC > 0 to avoid problems due to longjmp.
  80. X
  81. XNew -a and -e options to use awk or egrep style regexps, respectively,
  82. Xsince POSIX says awk should use egrep regexps.  Default is -a.
  83. X
  84. XAdded -v option for setting variables before the first file is encountered.
  85. XVersion information now uses -V and copyleft uses -C.
  86. X
  87. XAdded a patchlevel.h file and its use for -V and -C.
  88. X
  89. XAppend_right() optimized for major improvement to programs with a *lot*
  90. Xof statements.
  91. X
  92. XOperator precedence has been corrected to match draft Posix.
  93. X
  94. XTightened up grammar for builtin functions so that only length
  95. Xmay be called without arguments or parentheses.
  96. X
  97. X/regex/ is now a normal expression that can appear in any expression
  98. Xcontext.
  99. X
  100. XAllow /= to begin a regexp.  Allow ..[../..].. in a regexp.
  101. X
  102. XAllow empty compound statements ({}).
  103. X
  104. XMade return and next illegal outside a function and in BEGIN/END respectively.
  105. X
  106. XDivision by zero is now illegal and causes a fatal error.
  107. X
  108. XFixed exponentiation so that x ^ 0 and x ^= 0 both return 1.
  109. X
  110. XFixed do_sqrt, do_log, and do_exp to do argument/return checking and
  111. Xprint an error message, per the manual.
  112. X
  113. XFixed main to catch SIGSEGV to get source and data file line numbers.
  114. X
  115. XFixed yyerror to print the ^ at the beginning of the bad token, not the end.
  116. X
  117. XFix to substr() builtin:  it was failing if the arguments
  118. Xweren't already strings.
  119. X
  120. XAdded new node value flag NUMERIC to indicate that a variable is
  121. Xpurely a number as opposed to type NUM which indicates that
  122. Xthe node's numeric value is valid.  This is set in make_number(),
  123. Xtmp_number and r_force_number() when appropriate and used in
  124. Xcmp_nodes().  This fixed a bug in comparison of variables that had
  125. Xnumeric prefixes.  The new code uses strtod() and eliminates is_a_number().
  126. XA simple strtod() is provided for systems lacking one.  It does no
  127. Xoverflow checking, so could be improved.
  128. X
  129. XSimplification and efficiency improvement in force_string.
  130. X
  131. XAdded performance tweak in r_force_number().
  132. X
  133. XFixed a bug with nested loops and break/continue in functions.
  134. X
  135. XFixed inconsistency in handling of empty fields when $0 has to be rebuilt.
  136. XHappens to simplify rebuild_record().
  137. X
  138. XCleaned up the code associated with opening a pipe for reading.  Gawk
  139. Xnow has its own popen routine (gawk_popen) that allocates an IOBUF
  140. Xand keeps track of the pid of the child process.  gawk_pclose
  141. Xmarks the appropriate child as defunct in the right struct redirect.
  142. X
  143. XCleaned up and fixed close_redir().
  144. X
  145. XFixed an obscure bug to do with redirection.  Intermingled ">" and ">>"
  146. Xredirects did not output in a predictable order.
  147. X
  148. XImproved handling of output bufferring:  now all print[f]s redirected to a tty
  149. Xor pipe are flushed immediately and non-redirected output to a tty is flushed
  150. Xbefore the next input record is read.
  151. X
  152. XFixed a bug in get_a_record() where bcopy() could have copied over
  153. Xa random pointer.
  154. X
  155. XFixed a bug when RS="" and records separated by multiple blank lines.
  156. X
  157. XGot rid of SLOWIO code which was out-of-date anyway.
  158. X
  159. XFix in get_field() for case where $0 is changed and then $(n) are
  160. Xchanged and then $0 is used.
  161. X
  162. XFixed infinite loop on failure to open file for reading from getline.
  163. XNow handles redirect file open failures properly.
  164. X
  165. XFilenames such as /dev/stdin now allowed on the command line as well as
  166. Xin redirects.
  167. X
  168. XFixed so that gawk '$1' where $1 is a zero tests false.
  169. X
  170. XFixed parsing so that `RLENGTH -1' parses the same as `RLENGTH - 1',
  171. Xfor example.
  172. X
  173. XThe return from a user-defined function now defaults to the Null node.
  174. XThis fixes a core-dump-causing bug when the return value  of a function
  175. Xis used and that function returns no value.
  176. X
  177. XNow catches floating point exceptions to avoid core dumps.
  178. X
  179. XBug fix for deleting elements of an array -- under some conditions, it was
  180. Xdeleting more than one element at a time.
  181. X
  182. XFix in AWKPATH code for running off the end of the string.
  183. X
  184. XFixed handling of precision in *printf calls.  %0.2d now works properly,
  185. Xas does %c.  [s]printf now recognizes %i and %X.
  186. X
  187. XFixed a bug in printing of very large (>240) strings.
  188. X
  189. XCleaned up erroneous behaviour for RS == "".
  190. X
  191. XAdded IGNORECASE support to index().
  192. X
  193. XSimplified and fixed newnode/freenode.
  194. X
  195. XFixed reference to $(anything) in a BEGIN block.
  196. X
  197. XEliminated use of USG rand48().
  198. X
  199. XBug fix in force_string for machines with 16-bit ints.
  200. X
  201. XReplaced use of mktemp() with tmpnam() and provided a partial implementation of
  202. Xthe latter for systems that don't have it.
  203. X
  204. XAdded a portability check for includes in io.c.
  205. X
  206. XMinor portability fix in alloc.c plus addition of xmalloc().
  207. X
  208. XPortability fix:  on UMAX4.2, st_blksize is zero for a pipe, thus breaking
  209. Xiop_alloc() -- fixed.
  210. X
  211. XWorkaround for compiler bug on Sun386i in do_sprintf.
  212. X
  213. XMore and improved prototypes in awk.h.
  214. X
  215. XConsolidated C escape parsing code into one place.
  216. X
  217. Xstrict flag is now turned on only when invoked with compatability option.
  218. XIt now applies to fewer things.
  219. X
  220. XChanged cast of f._ptr in vprintf.c from (unsigned char *) to (char *).
  221. XHopefully this is right for the systems that use this code (I don't).
  222. X
  223. XSupport for pipes under MSDOS added.
  224. END_OF_FILE
  225.   if test 6927 -ne `wc -c <'./CHANGES'`; then
  226.     echo shar: \"'./CHANGES'\" unpacked with wrong size!
  227.   fi
  228.   # end of './CHANGES'
  229. fi
  230. if test -f './Makefile' -a "${1}" != "-c" ; then 
  231.   echo shar: Will not clobber existing file \"'./Makefile'\"
  232. else
  233.   echo shar: Extracting \"'./Makefile'\" \(7478 characters\)
  234.   sed "s/^X//" >'./Makefile' <<'END_OF_FILE'
  235. X# Makefile for GNU Awk.
  236. X#
  237. X# Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  238. X# 
  239. X# This file is part of GAWK, the GNU implementation of the
  240. X# AWK Progamming Language.
  241. X# 
  242. X# GAWK is free software; you can redistribute it and/or modify
  243. X# it under the terms of the GNU General Public License as published by
  244. X# the Free Software Foundation; either version 1, or (at your option)
  245. X# any later version.
  246. X# 
  247. X# GAWK is distributed in the hope that it will be useful,
  248. X# but WITHOUT ANY WARRANTY; without even the implied warranty of
  249. X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  250. X# GNU General Public License for more details.
  251. X# 
  252. X# You should have received a copy of the GNU General Public License
  253. X# along with GAWK; see the file COPYING.  If not, write to
  254. X# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  255. X
  256. X# User tunable macros
  257. X
  258. X# CFLAGS: options to the C compiler
  259. X#
  260. X#    -O    optimize
  261. X#    -g    include dbx/sdb info
  262. X#    -gg    include gdb debugging info; only for GCC (deprecated)
  263. X#    -pg    include new (gmon) profiling info
  264. X#    -p    include old style profiling info (System V)
  265. X#
  266. X#    To port GAWK, examine and adjust the following flags carefully.
  267. X#    In addition, you will have to look at alloca below.
  268. X#    The intent (eventual) is to not penalize the most-standard-conforming
  269. X#    systems with a lot of #define's.
  270. X#
  271. X#    -DBCOPY_MISSING        - bcopy() et al. are missing; will replace
  272. X#                  with a #define'd memcpy() et al. -- use at
  273. X#                  your own risk (should really use a memmove())
  274. X#    -DSPRINTF_INT        - sprintf() returns int (most USG systems)
  275. X#    -DBLKSIZE_MISSING    - st_blksize missing from stat() structure
  276. X#                  (most USG systems)
  277. X#    -DBSDSTDIO        - has a BSD internally-compatible stdio
  278. X#    -DDOPRNT_MISSING    - lacks doprnt() routine
  279. X#    -DDUP2_MISSING        - lacks dup2() system call (S5Rn, n < 4)
  280. X#    -DGCVT_MISSING        - lacks gcvt() routine
  281. X#    -DGETOPT_MISSING    - lacks getopt() routine
  282. X#    -DMEMCMP_MISSING    - lacks memcmp() routine
  283. X#    -DMEMCPY_MISSING    - lacks memcpy() routine
  284. X#    -DMEMSET_MISSING    - lacks memset() routine
  285. X#    -DRANDOM_MISSING    - lacks random() routine
  286. X#    -DSTRCASE_MISSING    - lacks strcasecmp() routine
  287. X#    -DSTRCHR_MISSING    - lacks strchr() and strrchr() routines
  288. X#    -DSTRERROR_MISSING    - lacks (ANSI C) strerror() routine
  289. X#    -DSTRTOD_MISSING    - lacks strtod() routine
  290. X#    -DTMPNAM_MISSING    - lacks or deficient tmpnam() routine
  291. X#    -DVPRINTF_MISSING    - lacks vprintf and associated routines
  292. X#    -DSIGTYPE=int        - signal routines return int (default void)
  293. X
  294. X# Sun running SunOS 4.x
  295. XMISSING = -DSTRERROR_MISSING -DSTRCASE_MISSING
  296. X
  297. X# SGI Personal Iris (Sys V derived)
  298. X# MISSING = -DSPRINTF_INT -DBLKSIZE_MISSING -DSTRERROR_MISSING -DRANDOM_MISSING
  299. X
  300. X# VAX running Ultrix 3.x
  301. X# MISSING = -DSTRERROR_MISSING
  302. X
  303. X# A generic 4.2 BSD machine
  304. X# (eliminate GETOPT_MISSING for 4.3 release)
  305. X# (eliminate STRCASE_MISSING and TMPNAM_MISSING for Tahoe release)
  306. X# MISSING = -DBSDSTDIO -DMEMCMP_MISSING -DMEMCPY_MISSING -DMEMSET_MISSING \
  307. X#    -DSTRERROR_MISSING -DSTRTOD_MISSING -DVPRINTF_MISSING \
  308. X#    -DSTRCASE_MISSING -DTMPNAM_MISSING \
  309. X#    -DGETOPT_MISSING -DSTRCHR_MISSING -DSIGTYPE=int
  310. X
  311. X# On Amdahl UTS, a SysVr2-derived system
  312. X# MISSING = -DBCOPY_MISSING -DSPRINTF_INT -DRANDOM_MISSING -DSTRERROR_MISSING \
  313. X#    -DSTRCASE_MISSING -DDUP2_MISSING # -DBLKSIZE_MISSING ??????
  314. X
  315. X# Comment out the next line if you don't have gcc.
  316. X# Also choose just one of -g and -O.
  317. XCC=         gcc
  318. X
  319. XOPTIMIZE=    -O -g
  320. XPROFILE=    #-pg
  321. XDEBUG=        #-DDEBUG #-DMEMDEBUG #-DFUNC_TRACE #-DMPROF
  322. XDEBUGGER=    #-g -Bstatic
  323. XWARN=        #-W -Wunused -Wimplicit -Wreturn-type -Wcomment    # for gcc only
  324. X
  325. X# Parser to use on grammar -- if you don't have bison use the first one
  326. X#PARSER = yacc
  327. XPARSER = bison
  328. X
  329. X# ALLOCA
  330. X#    Set equal to alloca.o if your system is S5 and you don't have
  331. X#    alloca. Uncomment one of the rules below to make alloca.o from
  332. X#    either alloca.s or alloca.c.
  333. XALLOCA= #alloca.o
  334. X
  335. X#
  336. X# With the exception of the alloca rule referred to above, you shouldn't
  337. X# need to customize this file below this point.
  338. X#
  339. X
  340. XFLAGS= $(MISSING) $(DEBUG)
  341. XCFLAGS= $(FLAGS) $(DEBUGGER) $(PROFILE) $(OPTIMIZE) $(WARN)
  342. X
  343. X# object files
  344. XAWKOBJS = main.o eval.o builtin.o msg.o debug.o io.o field.o array.o node.o \
  345. X        version.o missing.o
  346. X
  347. XALLOBJS = $(AWKOBJS) awk.tab.o
  348. X
  349. X# GNUOBJS
  350. X#    GNU stuff that gawk uses as library routines.
  351. XGNUOBJS= regex.o $(ALLOCA)
  352. X
  353. X# source and documentation files
  354. XSRC =    main.c eval.c builtin.c msg.c \
  355. X    debug.c io.c field.c array.c node.c missing.c
  356. X
  357. XALLSRC= $(SRC) awk.tab.c
  358. X
  359. XAWKSRC= awk.h awk.y $(ALLSRC) version.sh patchlevel.h
  360. X
  361. XGNUSRC = alloca.c alloca.s regex.c regex.h
  362. X
  363. XCOPIES = missing.d/dup2.c missing.d/gcvt.c missing.d/getopt.c \
  364. X    missing.d/memcmp.c missing.d/memcpy.c missing.d/memset.c \
  365. X    missing.d/random.c missing.d/strcase.c missing.d/strchr.c \
  366. X    missing.d/strerror.c missing.d/strtod.c missing.d/tmpnam.c \
  367. X    missing.d/vprintf.c
  368. X
  369. XSUPPORT = support/texindex.c support/texinfo.tex
  370. X
  371. XDOCS= gawk.1 gawk.texinfo
  372. X
  373. XINFOFILES= gawk-info gawk-info-1 gawk-info-2 gawk-info-3 gawk-info-4 \
  374. X       gawk-info-5 gawk-info-6 gawk.aux gawk.cp gawk.cps gawk.fn \
  375. X       gawk.fns gawk.ky gawk.kys gawk.pg gawk.pgs gawk.toc \
  376. X       gawk.tp gawk.tps gawk.vr gawk.vrs
  377. X
  378. XMISC = CHANGES COPYING FUTURES Makefile PROBLEMS README
  379. X
  380. XPCSTUFF= pc.d/Makefile.pc pc.d/popen.c pc.d/popen.h
  381. X
  382. XALLDOC= gawk.dvi $(INFOFILES)
  383. X
  384. XALLFILES= $(AWKSRC) $(GNUSRC) $(COPIES) $(MISC) $(DOCS) $(ALLDOC) $(PCSTUFF) $(SUPPORT)
  385. X
  386. X# Release of gawk.  There can be no leading or trailing white space here!
  387. XREL=2.11
  388. X
  389. X# rules to build gawk
  390. Xgawk: $(ALLOBJS) $(GNUOBJS)
  391. X    $(CC) -o gawk $(CFLAGS) $(ALLOBJS) $(GNUOBJS) -lm
  392. X
  393. X$(AWKOBJS): awk.h
  394. X
  395. Xmain.o: patchlevel.h
  396. X
  397. Xawk.tab.o: awk.h awk.tab.c
  398. X
  399. Xawk.tab.c: awk.y
  400. X    $(PARSER) -v awk.y
  401. X    -mv -f y.tab.c awk.tab.c
  402. X
  403. Xversion.c: version.sh
  404. X    sh version.sh $(REL) > version.c
  405. X
  406. X# Alloca: uncomment this if your system (notably System V boxen)
  407. X# does not have alloca in /lib/libc.a
  408. X#
  409. X#alloca.o: alloca.s
  410. X#    /lib/cpp < alloca.s | sed '/^#/d' > t.s
  411. X#    as t.s -o alloca.o
  412. X#    rm t.s
  413. X
  414. X# If your machine is not supported by the assembly version of alloca.s,
  415. X# use the C version instead.  This uses the default rules to make alloca.o.
  416. X#
  417. X#alloca.o: alloca.c
  418. X
  419. X# auxiliary rules for release maintenance
  420. Xlint: $(ALLSRC)
  421. X    lint -hcbax $(FLAGS) $(ALLSRC)
  422. X
  423. Xxref:
  424. X    cxref -c $(FLAGS) $(ALLSRC) | grep -v '    /' >xref
  425. X
  426. Xclean:
  427. X    rm -f gawk *.o core awk.output awk.tab.c gmon.out make.out version.c
  428. X
  429. Xclobber: clean
  430. X    rm -f $(ALLDOC) gawk.log
  431. X
  432. Xgawk.dvi: gawk.texinfo
  433. X    tex gawk.texinfo ; texindex gawk.??
  434. X    tex gawk.texinfo ; texindex gawk.??
  435. X    tex gawk.texinfo
  436. X
  437. X$(INFOFILES): gawk.texinfo
  438. X    makeinfo gawk.texinfo
  439. X
  440. Xsrcrelease: $(AWKSRC) $(GNUSRC) $(DOCS) $(MISC) $(COPIES) $(PCSTUFF) $(SUPPORT)
  441. X    -mkdir gawk-$(REL)
  442. X    cp -p $(AWKSRC) $(GNUSRC) $(DOCS) $(MISC) gawk-$(REL)
  443. X    -mkdir gawk-$(REL)/missing.d
  444. X    cp -p $(COPIES) gawk-$(REL)/missing.d
  445. X    -mkdir gawk-$(REL)/pc.d
  446. X    cp -p $(PCSTUFF) gawk-$(REL)/pc.d
  447. X    -mkdir gawk-$(REL)/support
  448. X    cp -p $(SUPPORT) gawk-$(REL)/support
  449. X    tar -cf - gawk-$(REL) | compress > gawk-$(REL).tar.Z
  450. X
  451. Xdocrelease: $(ALLDOC)
  452. X    -mkdir gawk-$(REL)-doc
  453. X    cp -p $(INFOFILES) gawk.dvi gawk-$(REL)-doc
  454. X    nroff -man gawk.1 > gawk-$(REL)-doc/gawk.1.pr
  455. X    tar -cf - gawk-$(REL)-doc | compress > gawk-doc-$(REL).tar.Z
  456. X
  457. Xpsrelease: docrelease
  458. X    -mkdir gawk-postscript
  459. X    dvi2ps gawk.dvi > gawk-postscript/gawk.postscript
  460. X    psroff -t -man gawk.1 > gawk-postscript/gawk.1.ps
  461. X    tar -cf - gawk-postscript | compress > gawk.postscript.tar.Z
  462. X
  463. Xrelease: srcrelease docrelease psrelease
  464. X    rm -fr gawk-postscript gawk-$(REL) gawk-$(REL)-doc
  465. X
  466. Xdiff:
  467. X    for i in RCS/*; do rcsdiff -c -b $$i > `basename $$i ,v`.diff; done
  468. END_OF_FILE
  469.   if test 7478 -ne `wc -c <'./Makefile'`; then
  470.     echo shar: \"'./Makefile'\" unpacked with wrong size!
  471.   fi
  472.   # end of './Makefile'
  473. fi
  474. if test -f './alloca.s' -a "${1}" != "-c" ; then 
  475.   echo shar: Will not clobber existing file \"'./alloca.s'\"
  476. else
  477.   echo shar: Extracting \"'./alloca.s'\" \(8394 characters\)
  478.   sed "s/^X//" >'./alloca.s' <<'END_OF_FILE'
  479. X/* `alloca' standard 4.2 subroutine for 68000's and 16000's and others.
  480. X   Also has _setjmp and _longjmp for pyramids.
  481. X   Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
  482. X
  483. XThis file is part of GNU Emacs.
  484. X
  485. XGNU Emacs is distributed in the hope that it will be useful,
  486. Xbut WITHOUT ANY WARRANTY.  No author or distributor
  487. Xaccepts responsibility to anyone for the consequences of using it
  488. Xor for whether it serves any particular purpose or works at all,
  489. Xunless he says so in writing.  Refer to the GNU Emacs General Public
  490. XLicense for full details.
  491. X
  492. XEveryone is granted permission to copy, modify and redistribute
  493. XGNU Emacs, but only under the conditions described in the
  494. XGNU Emacs General Public License.   A copy of this license is
  495. Xsupposed to have been given to you along with GNU Emacs so you
  496. Xcan know your rights and responsibilities.  It should be in a
  497. Xfile named COPYING.  Among other things, the copyright notice
  498. Xand this notice must be preserved on all copies.  */
  499. X
  500. X
  501. X/* Both 68000 systems I have run this on have had broken versions of alloca.
  502. X   Also, I am told that non-berkeley systems do not have it at all.
  503. X   So replace whatever system-provided alloca there may be
  504. X   on all 68000 systems.  */
  505. X
  506. X/* #include "config.h" */
  507. X
  508. X#ifndef HAVE_ALLOCA  /* define this to use system's alloca */
  509. X
  510. X#ifndef hp9000s300
  511. X#ifndef mc68k
  512. X#ifndef m68000
  513. X#ifndef WICAT
  514. X#ifndef ns16000
  515. X#ifndef sequent
  516. X#ifndef pyr
  517. X#ifndef ATT3B5
  518. X#ifndef XENIX
  519. Xyou
  520. Xlose!!
  521. X#endif /* XENIX */
  522. X#endif /* ATT3B5 */
  523. X#endif /* pyr */
  524. X#endif /* sequent */
  525. X#endif /* ns16000 */
  526. X#endif /* WICAT */
  527. X#endif /* m68000 */
  528. X#endif /* mc68k */
  529. X#endif /* hp9000s300 */
  530. X
  531. X
  532. X#ifdef hp9000s300
  533. X#ifdef OLD_HP_ASSEMBLER
  534. X    data
  535. X    text
  536. X    globl    _alloca
  537. X_alloca    
  538. X    move.l    (sp)+,a0    ; pop return addr from top of stack
  539. X    move.l    (sp)+,d0    ; pop size in bytes from top of stack
  540. X    add.l    #ROUND,d0    ; round size up to long word
  541. X    and.l    #MASK,d0    ; mask out lower two bits of size
  542. X    sub.l    d0,sp        ; allocate by moving stack pointer
  543. X    tst.b    PROBE(sp)    ; stack probe to allocate pages
  544. X    move.l    sp,d0        ; return pointer
  545. X    add.l    #-4,sp        ; new top of stack
  546. X    jmp    (a0)        ; not a normal return
  547. XMASK    equ    -4        ; Longword alignment
  548. XROUND    equ    3        ; ditto
  549. XPROBE    equ    -128        ; safety buffer for C compiler scratch
  550. X    data
  551. X#else /* new hp assembler syntax */
  552. X/*
  553. X  The new compiler does "move.m <registers> (%sp)" to save registers,
  554. X    so we must copy the saved registers when we mung the sp.
  555. X  The old compiler did "move.m <register> <offset>(%a6)", which
  556. X    gave us no trouble
  557. X */
  558. X    text
  559. X    set    PROBE,-128    # safety for C frame temporaries
  560. X    set    MAXREG,10    # d2-d7, a2-a5 may have been saved
  561. X    global    _alloca
  562. X_alloca:
  563. X    mov.l    (%sp)+,%a0    # return addess
  564. X    mov.l    (%sp)+,%d0    # number of bytes to allocate
  565. X    mov.l    %sp,%a1        # save old sp for register copy
  566. X    mov.l    %sp,%d1        # compute new sp
  567. X    sub.l    %d0,%d1        # space requested
  568. X    and.l    &-4,%d1        # round down to longword
  569. X    sub.l    &MAXREG*4,%d1    # space for saving registers
  570. X    mov.l    %d1,%sp        # save new value of sp
  571. X    tst.b    PROBE(%sp)    # create pages (sigh)
  572. X    move.w    &MAXREG-1,%d0
  573. Xcopy_regs_loop:            /* save caller's saved registers */
  574. X    mov.l    (%a1)+,(%sp)+
  575. X    dbra    %d0,copy_regs_loop
  576. X    mov.l    %sp,%d0        # return value
  577. X    mov.l    %d1,%sp
  578. X    add.l    &-4,%sp        # adjust tos
  579. X    jmp    (%a0)        # rts
  580. X#endif /* new hp assembler */
  581. X#else
  582. X#ifdef mc68k            /* SGS assembler totally different */
  583. X    file    "alloca.s"
  584. X    global    alloca
  585. Xalloca:
  586. X    mov.l    (%sp)+,%a1    # pop return addr from top of stack
  587. X    mov.l    (%sp)+,%d0    # pop size in bytes from top of stack
  588. X    add.l    &R%1,%d0    # round size up to long word
  589. X    and.l    &-4,%d0        # mask out lower two bits of size
  590. X    sub.l    %d0,%sp        # allocate by moving stack pointer
  591. X    tst.b    P%1(%sp)    # stack probe to allocate pages
  592. X    mov.l    %sp,%a0        # return pointer as pointer
  593. X    mov.l    %sp,%d0        # return pointer as int to avoid disaster
  594. X    add.l    &-4,%sp        # new top of stack
  595. X    jmp    (%a1)        # not a normal return
  596. X    set    S%1,64        # safety factor for C compiler scratch
  597. X    set    R%1,3+S%1    # add to size for rounding
  598. X    set    P%1,-132    # probe this far below current top of stack
  599. X
  600. X#else /* not mc68k */
  601. X
  602. X#ifdef m68000
  603. X
  604. X#ifdef WICAT
  605. X/*
  606. X * Registers are saved after the corresponding link so we have to explicitly
  607. X * move them to the top of the stack where they are expected to be.
  608. X * Since we do not know how many registers were saved in the calling function
  609. X * we must assume the maximum possible (d2-d7,a2-a5).  Hence, we end up
  610. X * wasting some space on the stack.
  611. X *
  612. X * The large probe (tst.b) attempts to make up for the fact that we have
  613. X * potentially used up the space that the caller probed for its own needs.
  614. X */
  615. X    .procss m0
  616. X    .config "68000 1"
  617. X    .module    _alloca
  618. XMAXREG:    .const    10
  619. X    .sect    text
  620. X    .global    _alloca
  621. X_alloca:
  622. X    move.l    (sp)+,a1    ; pop return address
  623. X    move.l    (sp)+,d0    ; pop allocation size
  624. X    move.l    sp,d1        ; get current SP value
  625. X    sub.l    d0,d1        ; adjust to reflect required size...
  626. X    sub.l    #MAXREG*4,d1    ; ...and space needed for registers
  627. X    and.l    #-4,d1        ; backup to longword boundry
  628. X    move.l    sp,a0        ; save old SP value for register copy
  629. X    move.l    d1,sp        ; set the new SP value
  630. X    tst.b    -4096(sp)    ; grab an extra page (to cover caller)
  631. X    move.l    a2,d1        ; save callers register
  632. X    move.l    sp,a2
  633. X    move.w    #MAXREG-1,d0    ; # of longwords to copy
  634. Xloop:    move.l    (a0)+,(a2)+    ; copy registers...
  635. X    dbra    d0,loop        ; ...til there are no more
  636. X    move.l    a2,d0        ; end of register area is addr for new space
  637. X    move.l    d1,a2        ; restore saved a2.
  638. X    addq.l    #4,sp        ; caller will increment sp by 4 after return.
  639. X    move.l    d0,a0        ; return value in both a0 and d0.
  640. X    jmp    (a1)
  641. X    .end    _alloca
  642. X#else
  643. X
  644. X/* Some systems want the _, some do not.  Win with both kinds.  */
  645. X.globl    _alloca
  646. X_alloca:
  647. X.globl    alloca
  648. Xalloca:
  649. X    movl    sp@+,a0
  650. X    movl    a7,d0
  651. X    subl    sp@,d0
  652. X    andl    #~3,d0
  653. X    movl    d0,sp
  654. X    tstb    sp@(0)        /* Make stack pages exist  */
  655. X                /* Needed on certain systems
  656. X                   that lack true demand paging */
  657. X    addql    #4,d0
  658. X    jmp    a0@
  659. X
  660. X#endif /* not WICAT */
  661. X#endif /* m68000 */
  662. X#endif /* not mc68k */
  663. X#endif /* not hp9000s300 */
  664. X
  665. X#ifdef ns16000
  666. X
  667. X    .text
  668. X    .align    2
  669. X/* Some systems want the _, some do not.  Win with both kinds.  */
  670. X.globl    _alloca
  671. X_alloca:
  672. X.globl    alloca
  673. Xalloca:
  674. X
  675. X/* Two different assembler syntaxes are used for the same code
  676. X    on different systems.  */
  677. X
  678. X#ifdef sequent
  679. X#define IM
  680. X#define REGISTER(x) x
  681. X#else
  682. X#define IM $
  683. X#define REGISTER(x) 0(x)
  684. X#endif
  685. X
  686. X/*
  687. X * The ns16000 is a little more difficult, need to copy regs.
  688. X * Also the code assumes direct linkage call sequence (no mod table crap).
  689. X * We have to copy registers, and therefore waste 32 bytes.
  690. X *
  691. X * Stack layout:
  692. X * new    sp ->    junk    
  693. X *         registers (copy)
  694. X *    r0 ->    new data        
  695. X *         |       (orig retval)
  696. X *         |      (orig arg)
  697. X * old  sp ->    regs      (orig)
  698. X *        local data
  699. X *    fp ->    old fp
  700. X */
  701. X
  702. X    movd    tos,r1        /*  pop return addr */
  703. X    negd    tos,r0        /*  pop amount to allocate */
  704. X    sprd    sp,r2
  705. X    addd    r2,r0
  706. X    bicb    IM/**/3,r0    /*  4-byte align */
  707. X    lprd    sp,r0
  708. X    adjspb    IM/**/36    /*  space for regs, +4 for caller to pop */
  709. X    movmd    0(r2),4(sp),IM/**/4    /*  copy regs */
  710. X    movmd    0x10(r2),0x14(sp),IM/**/4
  711. X    jump    REGISTER(r1)    /* funky return */
  712. X#endif /* ns16000 */
  713. X
  714. X#ifdef pyr
  715. X
  716. X.globl _alloca
  717. X
  718. X_alloca: addw $3,pr0    # add 3 (dec) to first argument
  719. X    bicw $3,pr0    # then clear its last 2 bits
  720. X    subw pr0,sp    # subtract from SP the val in PR0
  721. X    andw $-32,sp    # keep sp aligned on multiple of 32.
  722. X    movw sp,pr0    # ret. current SP
  723. X    ret
  724. X
  725. X#ifdef PYRAMID_OLD /* This isn't needed in system version 4.  */
  726. X.globl __longjmp
  727. X.globl _longjmp
  728. X.globl __setjmp
  729. X.globl _setjmp
  730. X
  731. X__longjmp: jump _longjmp
  732. X__setjmp:  jump _setjmp
  733. X#endif
  734. X
  735. X#endif /* pyr */
  736. X
  737. X#ifdef ATT3B5
  738. X
  739. X    .align 4
  740. X    .globl alloca
  741. X
  742. Xalloca:
  743. X    movw %ap, %r8
  744. X    subw2 $9*4, %r8
  745. X    movw 0(%r8), %r1    /* pc */
  746. X    movw 4(%r8), %fp
  747. X    movw 8(%r8), %sp
  748. X    addw2 %r0, %sp /* make room */
  749. X    movw %sp, %r0 /* return value */
  750. X    jmp (%r1) /* continue... */
  751. X
  752. X#endif /* ATT3B5 */
  753. X
  754. X#ifdef XENIX
  755. X
  756. X.386
  757. X
  758. X_TEXT segment dword use32 public 'CODE'
  759. Xassume   cs:_TEXT
  760. X
  761. X;-------------------------------------------------------------------------
  762. X
  763. Xpublic _alloca
  764. X_alloca proc near
  765. X
  766. X    pop    ecx        ; return address
  767. X    pop    eax        ; amount to alloc
  768. X    add    eax,3        ; round it to 32-bit boundary
  769. X    and    al,11111100B    ;
  770. X    mov    edx,esp        ; current sp in edx
  771. X    sub    edx,eax        ; lower the stack
  772. X    xchg    esp,edx        ; start of allocation in esp, old sp in edx
  773. X    mov    eax,esp        ; return ptr to base in eax
  774. X    push    [edx+8]        ; save poss. stored reg. values (esi,edi,ebx)
  775. X    push    [edx+4]        ;  on lowered stack
  776. X    push    [edx]        ;
  777. X    sub    esp,4        ; allow for 'add esp, 4'
  778. X    jmp    ecx        ; jump to return address
  779. X
  780. X_alloca endp
  781. X
  782. X_TEXT    ends
  783. X
  784. Xend
  785. X
  786. X#endif /* XENIX */
  787. X
  788. X#endif /* not HAVE_ALLOCA */
  789. END_OF_FILE
  790.   if test 8394 -ne `wc -c <'./alloca.s'`; then
  791.     echo shar: \"'./alloca.s'\" unpacked with wrong size!
  792.   fi
  793.   # end of './alloca.s'
  794. fi
  795. if test -f './field.c' -a "${1}" != "-c" ; then 
  796.   echo shar: Will not clobber existing file \"'./field.c'\"
  797. else
  798.   echo shar: Extracting \"'./field.c'\" \(10555 characters\)
  799.   sed "s/^X//" >'./field.c' <<'END_OF_FILE'
  800. X/*
  801. X * field.c - routines for dealing with fields and record parsing
  802. X */
  803. X
  804. X/* 
  805. X * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  806. X * 
  807. X * This file is part of GAWK, the GNU implementation of the
  808. X * AWK Progamming Language.
  809. X * 
  810. X * GAWK is free software; you can redistribute it and/or modify
  811. X * it under the terms of the GNU General Public License as published by
  812. X * the Free Software Foundation; either version 1, or (at your option)
  813. X * any later version.
  814. X * 
  815. X * GAWK is distributed in the hope that it will be useful,
  816. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  817. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  818. X * GNU General Public License for more details.
  819. X * 
  820. X * You should have received a copy of the GNU General Public License
  821. X * along with GAWK; see the file COPYING.  If not, write to
  822. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  823. X */
  824. X
  825. X#include "awk.h"
  826. X
  827. Xextern void assoc_clear();
  828. Xextern int a_get_three();
  829. Xextern int get_rs();
  830. X
  831. Xstatic char *get_fs();
  832. Xstatic int re_split();
  833. Xstatic int parse_fields();
  834. Xstatic void set_element();
  835. X
  836. Xchar *line_buf = NULL;    /* holds current input line */
  837. X
  838. Xstatic char *parse_extent;    /* marks where to restart parse of record */
  839. Xstatic int parse_high_water=0;    /* field number that we have parsed so far */
  840. Xstatic char f_empty[] = "";
  841. Xstatic char *save_fs = " ";    /* save current value of FS when line is read,
  842. X                 * to be used in deferred parsing
  843. X                 */
  844. X
  845. X
  846. XNODE **fields_arr;        /* array of pointers to the field nodes */
  847. XNODE node0;            /* node for $0 which never gets free'd */
  848. Xint node0_valid = 1;        /* $(>0) has not been changed yet */
  849. X
  850. Xvoid
  851. Xinit_fields()
  852. X{
  853. X    emalloc(fields_arr, NODE **, sizeof(NODE *), "init_fields");
  854. X    node0.type = Node_val;
  855. X    node0.stref = 0;
  856. X    node0.stptr = "";
  857. X    node0.flags = (STR|PERM);    /* never free buf */
  858. X    fields_arr[0] = &node0;
  859. X}
  860. X
  861. X/*
  862. X * Danger!  Must only be called for fields we know have just been blanked, or
  863. X * fields we know don't exist yet.  
  864. X */
  865. X
  866. X/*ARGSUSED*/
  867. Xstatic void
  868. Xset_field(num, str, len, dummy)
  869. Xint num;
  870. Xchar *str;
  871. Xint len;
  872. XNODE *dummy;    /* not used -- just to make interface same as set_element */
  873. X{
  874. X    NODE *n;
  875. X    int t;
  876. X    static int nf_high_water = 0;
  877. X
  878. X    if (num > nf_high_water) {
  879. X        erealloc(fields_arr, NODE **, (num + 1) * sizeof(NODE *), "set_field");
  880. X        nf_high_water = num;
  881. X    }
  882. X    /* fill in fields that don't exist */
  883. X    for (t = parse_high_water + 1; t < num; t++)
  884. X        fields_arr[t] = Nnull_string;
  885. X    n = make_string(str, len);
  886. X    (void) force_number(n);
  887. X    fields_arr[num] = n;
  888. X    parse_high_water = num;
  889. X}
  890. X
  891. X/* Someone assigned a value to $(something).  Fix up $0 to be right */
  892. Xstatic void
  893. Xrebuild_record()
  894. X{
  895. X    register int tlen;
  896. X    register NODE *tmp;
  897. X    NODE *ofs;
  898. X    char *ops;
  899. X    register char *cops;
  900. X    register NODE **ptr;
  901. X    register int ofslen;
  902. X
  903. X    tlen = 0;
  904. X    ofs = force_string(OFS_node->var_value);
  905. X    ofslen = ofs->stlen;
  906. X    ptr = &fields_arr[parse_high_water];
  907. X    while (ptr > &fields_arr[0]) {
  908. X        tmp = force_string(*ptr);
  909. X        tlen += tmp->stlen;
  910. X        ptr--;
  911. X    }
  912. X    tlen += (parse_high_water - 1) * ofslen;
  913. X    emalloc(ops, char *, tlen + 1, "fix_fields");
  914. X    cops = ops;
  915. X    ops[0] = '\0';
  916. X    for (ptr = &fields_arr[1]; ptr <= &fields_arr[parse_high_water]; ptr++) {
  917. X        tmp = *ptr;
  918. X        if (tmp->stlen == 1)
  919. X            *cops++ = tmp->stptr[0];
  920. X        else if (tmp->stlen != 0) {
  921. X            memcpy(cops, tmp->stptr, tmp->stlen);
  922. X            cops += tmp->stlen;
  923. X        }
  924. X        if (ptr != &fields_arr[parse_high_water]) {
  925. X            if (ofslen == 1)
  926. X                *cops++ = ofs->stptr[0];
  927. X            else if (ofslen != 0) {
  928. X                memcpy(cops, ofs->stptr, ofslen);
  929. X                cops += ofslen;
  930. X            }
  931. X        }
  932. X    }
  933. X    tmp = make_string(ops, tlen);
  934. X    free(ops);
  935. X    deref = fields_arr[0];
  936. X    do_deref();
  937. X    fields_arr[0] = tmp;
  938. X}
  939. X
  940. X/*
  941. X * setup $0, but defer parsing rest of line until reference is made to $(>0)
  942. X * or to NF.  At that point, parse only as much as necessary.
  943. X */
  944. Xvoid
  945. Xset_record(buf, cnt)
  946. Xchar *buf;
  947. Xint cnt;
  948. X{
  949. X    register int i;
  950. X
  951. X    assign_number(&NF_node->var_value, (AWKNUM)-1);
  952. X    for (i = 1; i <= parse_high_water; i++) {
  953. X        deref = fields_arr[i];
  954. X        do_deref();
  955. X    }
  956. X    parse_high_water = 0;
  957. X    node0_valid = 1;
  958. X    if (buf == line_buf) {
  959. X        deref = fields_arr[0];
  960. X        do_deref();
  961. X        save_fs = get_fs();
  962. X        node0.type = Node_val;
  963. X        node0.stptr = buf;
  964. X        node0.stlen = cnt;
  965. X        node0.stref = 1;
  966. X        node0.flags = (STR|PERM);    /* never free buf */
  967. X        fields_arr[0] = &node0;
  968. X    }
  969. X}
  970. X
  971. XNODE **
  972. Xget_field(num, assign)
  973. Xint num;
  974. Xint assign;    /* this field is on the LHS of an assign */
  975. X{
  976. X    int n;
  977. X
  978. X    /*
  979. X     * if requesting whole line but some other field has been altered,
  980. X     * then the whole line must be rebuilt
  981. X     */
  982. X    if (num == 0 && (node0_valid == 0 || assign)) {
  983. X        /* first, parse remainder of input record */
  984. X        if (NF_node->var_value->numbr == -1) {
  985. X            if (parse_high_water == 0)
  986. X                parse_extent = node0.stptr;
  987. X            n = parse_fields(HUGE-1, &parse_extent,
  988. X                    node0.stlen - (parse_extent - node0.stptr),
  989. X                    save_fs, set_field, (NODE *)NULL);
  990. X            assign_number(&NF_node->var_value, (AWKNUM)n);
  991. X        }
  992. X        if (node0_valid == 0)
  993. X            rebuild_record();
  994. X        return &fields_arr[0];
  995. X    }
  996. X    if (num > 0 && assign)
  997. X        node0_valid = 0;
  998. X    if (num <= parse_high_water)    /* we have already parsed this field */
  999. X        return &fields_arr[num];
  1000. X    if (parse_high_water == 0 && num > 0)    /* starting at the beginning */
  1001. X        parse_extent = fields_arr[0]->stptr;
  1002. X    /*
  1003. X     * parse up to num fields, calling set_field() for each, and saving
  1004. X     * in parse_extent the point where the parse left off
  1005. X     */
  1006. X    n = parse_fields(num, &parse_extent,
  1007. X        fields_arr[0]->stlen - (parse_extent-fields_arr[0]->stptr),
  1008. X        save_fs, set_field, (NODE *)NULL);
  1009. X    if (num == HUGE-1)
  1010. X        num = n;
  1011. X    if (n < num) {    /* requested field number beyond end of record;
  1012. X             * set_field will just extend the number of fields,
  1013. X             * with empty fields
  1014. X             */
  1015. X        set_field(num, f_empty, 0, (NODE *) NULL);
  1016. X        /*
  1017. X         * if this field is onthe LHS of an assignment, then we want to
  1018. X         * set NF to this value, below
  1019. X         */
  1020. X        if (assign)
  1021. X            n = num;
  1022. X    }
  1023. X    /*
  1024. X     * if we reached the end of the record, set NF to the number of fields
  1025. X     * so far.  Note that num might actually refer to a field that
  1026. X     * is beyond the end of the record, but we won't set NF to that value at
  1027. X     * this point, since this is only a reference to the field and NF
  1028. X     * only gets set if the field is assigned to -- in this case n has
  1029. X     * been set to num above
  1030. X     */
  1031. X    if (*parse_extent == '\0')
  1032. X        assign_number(&NF_node->var_value, (AWKNUM)n);
  1033. X
  1034. X    return &fields_arr[num];
  1035. X}
  1036. X
  1037. X/*
  1038. X * this is called both from get_field() and from do_split()
  1039. X */
  1040. Xstatic int
  1041. Xparse_fields(up_to, buf, len, fs, set, n)
  1042. Xint up_to;    /* parse only up to this field number */
  1043. Xchar **buf;    /* on input: string to parse; on output: point to start next */
  1044. Xint len;
  1045. Xregister char *fs;
  1046. Xvoid (*set) ();    /* routine to set the value of the parsed field */
  1047. XNODE *n;
  1048. X{
  1049. X    char *s = *buf;
  1050. X    register char *field;
  1051. X    register char *scan;
  1052. X    register char *end = s + len;
  1053. X    int NF = parse_high_water;
  1054. X    char rs = get_rs();
  1055. X
  1056. X
  1057. X    if (up_to == HUGE)
  1058. X        NF = 0;
  1059. X    if (*fs && *(fs + 1) != '\0') {    /* fs is a regexp */
  1060. X        struct re_registers reregs;
  1061. X
  1062. X        scan = s;
  1063. X        if (rs == 0 && STREQ(FS_node->var_value->stptr, " ")) {
  1064. X            while ((*scan == '\n' || *scan == ' ' || *scan == '\t')
  1065. X                && scan < end)
  1066. X                scan++;
  1067. X        }
  1068. X        s = scan;
  1069. X        while (scan < end
  1070. X            && re_split(scan, (int)(end - scan), fs, &reregs) != -1
  1071. X            && NF < up_to) {
  1072. X            if (reregs.end[0] == 0) {    /* null match */
  1073. X                scan++;
  1074. X                if (scan == end) {
  1075. X                    (*set)(++NF, s, scan - s, n);
  1076. X                    up_to = NF;
  1077. X                    break;
  1078. X                }
  1079. X                continue;
  1080. X            }
  1081. X            (*set)(++NF, s, scan - s + reregs.start[0], n);
  1082. X            scan += reregs.end[0];
  1083. X            s = scan;
  1084. X        }
  1085. X        if (NF != up_to && scan <= end) {
  1086. X            if (!(rs == 0 && scan == end)) {
  1087. X                (*set)(++NF, scan, (int)(end - scan), n);
  1088. X                scan = end;
  1089. X            }
  1090. X        }
  1091. X        *buf = scan;
  1092. X        return (NF);
  1093. X    }
  1094. X    for (scan = s; scan < end && NF < up_to; scan++) {
  1095. X        /*
  1096. X         * special case:  fs is single space, strip leading
  1097. X         * whitespace 
  1098. X         */
  1099. X        if (*fs == ' ') {
  1100. X            while ((*scan == ' ' || *scan == '\t') && scan < end)
  1101. X                scan++;
  1102. X            if (scan >= end)
  1103. X                break;
  1104. X        }
  1105. X        field = scan;
  1106. X        if (*fs == ' ')
  1107. X            while (*scan != ' ' && *scan != '\t' && scan < end)
  1108. X                scan++;
  1109. X        else {
  1110. X            while (*scan != *fs && scan < end)
  1111. X                scan++;
  1112. X            if (rs && scan == end-1 && *scan == *fs) {
  1113. X                (*set)(++NF, field, (int)(scan - field), n);
  1114. X                field = scan;
  1115. X            }
  1116. X        }
  1117. X        (*set)(++NF, field, (int)(scan - field), n);
  1118. X        if (scan == end)
  1119. X            break;
  1120. X    }
  1121. X    *buf = scan;
  1122. X    return NF;
  1123. X}
  1124. X
  1125. Xstatic int
  1126. Xre_split(buf, len, fs, reregsp)
  1127. Xchar *buf, *fs;
  1128. Xint len;
  1129. Xstruct re_registers *reregsp;
  1130. X{
  1131. X    typedef struct re_pattern_buffer RPAT;
  1132. X    static RPAT *rp;
  1133. X    static char *last_fs = NULL;
  1134. X
  1135. X    if ((last_fs != NULL && !STREQ(fs, last_fs))
  1136. X        || (rp && ! strict && ((IGNORECASE_node->var_value->numbr != 0)
  1137. X             ^ (rp->translate != NULL))))
  1138. X    {
  1139. X        /* fs has changed or IGNORECASE has changed */
  1140. X        free(rp->buffer);
  1141. X        free(rp->fastmap);
  1142. X        free((char *) rp);
  1143. X        free(last_fs);
  1144. X        last_fs = NULL;
  1145. X    }
  1146. X    if (last_fs == NULL) {    /* first time */
  1147. X        emalloc(rp, RPAT *, sizeof(RPAT), "re_split");
  1148. X        memset((char *) rp, 0, sizeof(RPAT));
  1149. X        emalloc(rp->buffer, char *, 8, "re_split");
  1150. X        rp->allocated = 8;
  1151. X        emalloc(rp->fastmap, char *, 256, "re_split");
  1152. X        emalloc(last_fs, char *, strlen(fs) + 1, "re_split");
  1153. X        (void) strcpy(last_fs, fs);
  1154. X        if (! strict && IGNORECASE_node->var_value->numbr != 0.0)
  1155. X            rp->translate = casetable;
  1156. X        else
  1157. X            rp->translate = NULL;
  1158. X        if (re_compile_pattern(fs, strlen(fs), rp) != NULL)
  1159. X            fatal("illegal regular expression for FS: `%s'", fs);
  1160. X    }
  1161. X    return re_search(rp, buf, len, 0, len, reregsp);
  1162. X}
  1163. X
  1164. XNODE *
  1165. Xdo_split(tree)
  1166. XNODE *tree;
  1167. X{
  1168. X    NODE *t1, *t2, *t3;
  1169. X    register char *splitc;
  1170. X    char *s;
  1171. X    NODE *n;
  1172. X
  1173. X    if (a_get_three(tree, &t1, &t2, &t3) < 3)
  1174. X        splitc = get_fs();
  1175. X    else
  1176. X        splitc = force_string(t3)->stptr;
  1177. X
  1178. X    n = t2;
  1179. X    if (t2->type == Node_param_list)
  1180. X        n = stack_ptr[t2->param_cnt];
  1181. X    if (n->type != Node_var && n->type != Node_var_array)
  1182. X        fatal("second argument of split is not a variable");
  1183. X    assoc_clear(n);
  1184. X
  1185. X    tree = force_string(t1);
  1186. X
  1187. X    s = tree->stptr;
  1188. X    return tmp_number((AWKNUM)
  1189. X        parse_fields(HUGE, &s, tree->stlen, splitc, set_element, n));
  1190. X}
  1191. X
  1192. Xstatic char *
  1193. Xget_fs()
  1194. X{
  1195. X    register NODE *tmp;
  1196. X    static char buf[10];
  1197. X
  1198. X    tmp = force_string(FS_node->var_value);
  1199. X    if (get_rs() == 0) {
  1200. X        if (tmp->stlen == 1) {
  1201. X            if (tmp->stptr[0] == ' ')
  1202. X                (void) strcpy(buf, "[     \n]+");
  1203. X            else
  1204. X                sprintf(buf, "[%c\n]", tmp->stptr[0]);
  1205. X        } else if (tmp->stlen == 0) {
  1206. X            buf[0] = '\n';
  1207. X            buf[1] = '\0';
  1208. X        } else
  1209. X            return tmp->stptr;
  1210. X        return buf;
  1211. X    }
  1212. X    return tmp->stptr;
  1213. X}
  1214. X
  1215. Xstatic void
  1216. Xset_element(num, s, len, n)
  1217. Xint num;
  1218. Xchar *s;
  1219. Xint len;
  1220. XNODE *n;
  1221. X{
  1222. X    *assoc_lookup(n, tmp_number((AWKNUM) (num))) = make_string(s, len);
  1223. X}
  1224. END_OF_FILE
  1225.   if test 10555 -ne `wc -c <'./field.c'`; then
  1226.     echo shar: \"'./field.c'\" unpacked with wrong size!
  1227.   fi
  1228.   # end of './field.c'
  1229. fi
  1230. if test -f './gawk.texinfo.07' -a "${1}" != "-c" ; then 
  1231.   echo shar: Will not clobber existing file \"'./gawk.texinfo.07'\"
  1232. else
  1233.   echo shar: Extracting \"'./gawk.texinfo.07'\" \(6852 characters\)
  1234.   sed "s/^X//" >'./gawk.texinfo.07' <<'END_OF_FILE'
  1235. XConcatenating two strings means sticking them together, one after another,
  1236. Xgiving a new string.  For example, the string @samp{foo} concatenated with
  1237. Xthe string @samp{bar} gives the string @samp{foobar}.
  1238. X@xref{Concatenation}.@refill
  1239. X
  1240. X@item Conditional Expression
  1241. XAn expression using the @samp{?:} ternary operator, such as
  1242. X@code{@var{expr1} ? @var{expr2} : @var{expr3}}.  The expression
  1243. X@var{expr1} is evaluated; if the result is true, the value of the whole
  1244. Xexpression is the value of @var{expr2} otherwise the value is
  1245. X@var{expr3}.  In either case, only one of @var{expr2} and @var{expr3}
  1246. Xis evaluated.  @xref{Conditional Exp}.@refill
  1247. X
  1248. X@item Constant Regular Expression
  1249. XA constant regular expression is a regular expression written within
  1250. Xslashes, such as @samp{/foo/}.  This regular expression is chosen
  1251. Xwhen you write the @code{awk} program, and cannot be changed doing
  1252. Xits execution.  @xref{Regexp Usage}.
  1253. X
  1254. X@item Comparison Expression
  1255. XA relation that is either true or false, such as @code{(a < b)}.
  1256. XComparison expressions are used in @code{if} and @code{while} statements,
  1257. Xand in patterns to select which input records to process.
  1258. X@xref{Comparison Ops}.@refill
  1259. X
  1260. X@item Curly Braces
  1261. XThe characters @samp{@{} and @samp{@}}.  Curly braces are used in
  1262. X@code{awk} for delimiting actions, compound statements, and function
  1263. Xbodies.@refill
  1264. X
  1265. X@item Data Objects
  1266. XThese are numbers and strings of characters.  Numbers are converted into
  1267. Xstrings and vice versa, as needed.  @xref{Conversion}.@refill
  1268. X
  1269. X@item Dynamic Regular Expression
  1270. XA dynamic regular expression is a regular expression written as an
  1271. Xordinary expression.  It could be a string constant, such as
  1272. X@code{"foo"}, but it may also be an expression whose value may vary.
  1273. X@xref{Regexp Usage}.
  1274. X
  1275. X@item Escape Sequences
  1276. XA special sequence of characters used for describing nonprinting
  1277. Xcharacters, such as @samp{\n} for newline, or @samp{\033} for the ASCII
  1278. XESC (escape) character.  @xref{Constants}.
  1279. X
  1280. X@item Field
  1281. XWhen @code{awk} reads an input record, it splits the record into pieces
  1282. Xseparated by whitespace (or by a separator regexp which you can
  1283. Xchange by setting the built-in variable @code{FS}).  Such pieces are
  1284. Xcalled fields.  @xref{Records}.@refill
  1285. X
  1286. X@item Format
  1287. XFormat strings are used to control the appearance of output in the
  1288. X@code{printf} statement.  Also, data conversions from numbers to strings
  1289. Xare controlled by the format string contained in the built-in variable
  1290. X@code{OFMT}.  @xref{Control Letters}; also @pxref{Output Separators}.@refill
  1291. X
  1292. X@item Function
  1293. XA specialized group of statements often used to encapsulate general
  1294. Xor program-specific tasks.  @code{awk} has a number of built-in
  1295. Xfunctions, and also allows you to define your own.  @xref{Built-in};
  1296. Xalso @pxref{User-defined}.
  1297. X
  1298. X@item @code{gawk}
  1299. XThe GNU implementation of @code{awk}.
  1300. X
  1301. X@item Input Record
  1302. XA single chunk of data read in by @code{awk}.  Usually, an @code{awk} input
  1303. Xrecord consists of one line of text.  @xref{Records}.@refill
  1304. X
  1305. X@item Keyword
  1306. XIn the @code{awk} language, a keyword is a word that has special
  1307. Xmeaning.  Keywords are reserved and may not be used as variable names.
  1308. X
  1309. XThe keywords of @code{awk} are:
  1310. X@code{if},
  1311. X@code{else},
  1312. X@code{while},
  1313. X@code{do@dots{}while},
  1314. X@code{for},
  1315. X@code{for@dots{}in},
  1316. X@code{break},
  1317. X@code{continue},
  1318. X@code{delete},
  1319. X@code{next},
  1320. X@code{function},
  1321. X@code{func},
  1322. Xand @code{exit}.@refill
  1323. X
  1324. X@item Lvalue
  1325. XAn expression that can appear on the left side of an assignment
  1326. Xoperator.  In most languages, lvalues can be variables or array
  1327. Xelements.  In @code{awk}, a field designator can also be used as an
  1328. Xlvalue.@refill
  1329. X
  1330. X@item Number
  1331. XA numeric valued data object.  The @code{gawk} implementation uses double
  1332. Xprecision floating point to represent numbers.@refill
  1333. X
  1334. X@item Pattern
  1335. XPatterns tell @code{awk} which input records are interesting to which
  1336. Xrules.
  1337. X
  1338. XA pattern is an arbitrary conditional expression against which input is
  1339. Xtested.  If the condition is satisfied, the pattern is said to @dfn{match}
  1340. Xthe input record.  A typical pattern might compare the input record against
  1341. Xa regular expression.  @xref{Patterns}.@refill
  1342. X
  1343. X@item Range (of input lines)
  1344. XA sequence of consecutive lines from the input file.  A pattern
  1345. Xcan specify ranges of input lines for @code{awk} to process, or it can
  1346. Xspecify single lines.  @xref{Patterns}.@refill
  1347. X
  1348. X@item Recursion
  1349. XWhen a function calls itself, either directly or indirectly.
  1350. XIf this isn't clear, refer to the entry for ``recursion''.
  1351. X
  1352. X@item Redirection
  1353. XRedirection means performing input from other than the standard input
  1354. Xstream, or output to other than the standard output stream.
  1355. X
  1356. XYou can redirect the output of the @code{print} and @code{printf} statements
  1357. Xto a file or a system command, using the @samp{>}, @samp{>>}, and @samp{|}
  1358. Xoperators.  You can redirect input to the @code{getline} statement using
  1359. Xthe @samp{<} and @samp{|} operators.  @xref{Redirection}.@refill
  1360. X
  1361. X@item Regular Expression
  1362. XSee ``regexp''.
  1363. X
  1364. X@item Regexp
  1365. XShort for @dfn{regular expression}.  A regexp is a pattern that denotes a
  1366. Xset of strings, possibly an infinite set.  For example, the regexp
  1367. X@samp{R.*xp} matches any string starting with the letter @samp{R}
  1368. Xand ending with the letters @samp{xp}.  In @code{awk}, regexps are
  1369. Xused in patterns and in conditional expressions.  Regexps may contain
  1370. Xescape sequences.  @xref{Regexp}.@refill
  1371. X
  1372. X@item Rule
  1373. XA segment of an @code{awk} program, that specifies how to process single
  1374. Xinput records.  A rule consists of a @dfn{pattern} and an @dfn{action}.
  1375. X@code{awk} reads an input record; then, for each rule, if the input record
  1376. Xsatisfies the rule's pattern, @code{awk} executes the rule's action.
  1377. XOtherwise, the rule does nothing for that input record.@refill
  1378. X
  1379. X@item Side Effect
  1380. XA side effect occurs when an expression has an effect aside from merely
  1381. Xproducing a value.  Assignment expressions, increment expressions and
  1382. Xfunction calls have side effects.  @xref{Assignment Ops}.
  1383. X
  1384. X@item Special File
  1385. XA file name interpreted internally by @code{gawk}, instead of being handed
  1386. Xdirectly to the underlying operating system.  For example, @file{/dev/stdin}.
  1387. X@xref{Special Files}.
  1388. X
  1389. X@item Stream Editor
  1390. XA program that reads records from an input stream and processes them one
  1391. Xor more at a time.  This is in contrast with batch programs, which may
  1392. Xexpect to read their input files in entirety before starting to do
  1393. Xanything, and with interactive programs, which require input from the
  1394. Xuser.@refill
  1395. X
  1396. X@item String
  1397. XA datum consisting of a sequence of characters, such as @samp{I am a
  1398. Xstring}.  Constant strings are written with double-quotes in the
  1399. X@code{awk} language, and may contain @dfn{escape sequences}.
  1400. X@xref{Constants}.
  1401. X
  1402. X@item Whitespace
  1403. XA sequence of blank or tab characters occurring inside an input record or a
  1404. Xstring.@refill
  1405. X@end table
  1406. X
  1407. X@node Index, , Glossary, Top
  1408. X@unnumbered Index
  1409. X@printindex cp
  1410. X
  1411. X@summarycontents
  1412. X@contents
  1413. X@bye
  1414. END_OF_FILE
  1415.   if test 6852 -ne `wc -c <'./gawk.texinfo.07'`; then
  1416.     echo shar: \"'./gawk.texinfo.07'\" unpacked with wrong size!
  1417.   fi
  1418.   # end of './gawk.texinfo.07'
  1419. fi
  1420. if test -f './node.c' -a "${1}" != "-c" ; then 
  1421.   echo shar: Will not clobber existing file \"'./node.c'\"
  1422. else
  1423.   echo shar: Extracting \"'./node.c'\" \(6310 characters\)
  1424.   sed "s/^X//" >'./node.c' <<'END_OF_FILE'
  1425. X/*
  1426. X * node.c -- routines for node management
  1427. X */
  1428. X
  1429. X/* 
  1430. X * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  1431. X * 
  1432. X * This file is part of GAWK, the GNU implementation of the
  1433. X * AWK Progamming Language.
  1434. X * 
  1435. X * GAWK is free software; you can redistribute it and/or modify
  1436. X * it under the terms of the GNU General Public License as published by
  1437. X * the Free Software Foundation; either version 1, or (at your option)
  1438. X * any later version.
  1439. X * 
  1440. X * GAWK is distributed in the hope that it will be useful,
  1441. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1442. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1443. X * GNU General Public License for more details.
  1444. X * 
  1445. X * You should have received a copy of the GNU General Public License
  1446. X * along with GAWK; see the file COPYING.  If not, write to
  1447. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  1448. X */
  1449. X
  1450. X#include "awk.h"
  1451. X
  1452. Xextern double strtod();
  1453. X
  1454. X/*
  1455. X * We can't dereference a variable until after we've given it its new value.
  1456. X * This variable points to the value we have to free up 
  1457. X */
  1458. XNODE *deref;
  1459. X
  1460. XAWKNUM
  1461. Xr_force_number(n)
  1462. XNODE *n;
  1463. X{
  1464. X    char *ptr;
  1465. X
  1466. X#ifdef DEBUG
  1467. X    if (n == NULL)
  1468. X        cant_happen();
  1469. X    if (n->type != Node_val)
  1470. X        cant_happen();
  1471. X    if(n->flags == 0)
  1472. X        cant_happen();
  1473. X    if (n->flags & NUM)
  1474. X        return n->numbr;
  1475. X#endif
  1476. X    if (n->stlen == 0)
  1477. X        n->numbr = 0.0;
  1478. X    else if (n->stlen == 1) {
  1479. X        if (isdigit(n->stptr[0])) {
  1480. X            n->numbr = n->stptr[0] - '0';
  1481. X            n->flags |= NUMERIC;
  1482. X        } else
  1483. X            n->numbr = 0.0;
  1484. X    } else {
  1485. X        errno = 0;
  1486. X        n->numbr = (AWKNUM) strtod(n->stptr, &ptr);
  1487. X        /* the following >= should be ==, but for SunOS 3.5 strtod() */
  1488. X        if (errno == 0 && ptr >= n->stptr + n->stlen)
  1489. X            n->flags |= NUMERIC;
  1490. X    }
  1491. X    n->flags |= NUM;
  1492. X    return n->numbr;
  1493. X}
  1494. X
  1495. X/*
  1496. X * the following lookup table is used as an optimization in force_string
  1497. X * (more complicated) variations on this theme didn't seem to pay off, but 
  1498. X * systematic testing might be in order at some point
  1499. X */
  1500. Xstatic char *values[] = {
  1501. X    "0",
  1502. X    "1",
  1503. X    "2",
  1504. X    "3",
  1505. X    "4",
  1506. X    "5",
  1507. X    "6",
  1508. X    "7",
  1509. X    "8",
  1510. X    "9",
  1511. X};
  1512. X#define    NVAL    (sizeof(values)/sizeof(values[0]))
  1513. X
  1514. XNODE *
  1515. Xr_force_string(s)
  1516. XNODE *s;
  1517. X{
  1518. X    char buf[128];
  1519. X    char *fmt;
  1520. X    long num;
  1521. X    char *sp = buf;
  1522. X
  1523. X#ifdef DEBUG
  1524. X    if (s == NULL)
  1525. X        cant_happen();
  1526. X    if (s->type != Node_val)
  1527. X        cant_happen();
  1528. X    if (s->flags & STR)
  1529. X        return s;
  1530. X    if (!(s->flags & NUM))
  1531. X        cant_happen();
  1532. X    if (s->stref != 0)
  1533. X        cant_happen();
  1534. X#endif
  1535. X    s->flags |= STR;
  1536. X    /* should check validity of user supplied OFMT */
  1537. X    fmt = OFMT_node->var_value->stptr;
  1538. X    if ((num = s->numbr) == s->numbr) {
  1539. X        /* integral value */
  1540. X        if (num < NVAL && num >= 0) {
  1541. X            sp = values[num];
  1542. X            s->stlen = 1;
  1543. X        } else {
  1544. X            (void) sprintf(sp, "%ld", num);
  1545. X            s->stlen = strlen(sp);
  1546. X        }
  1547. X    } else {
  1548. X        (void) sprintf(sp, fmt, s->numbr);
  1549. X        s->stlen = strlen(sp);
  1550. X    }
  1551. X    s->stref = 1;
  1552. X    emalloc(s->stptr, char *, s->stlen + 1, "force_string");
  1553. X    memcpy(s->stptr, sp, s->stlen+1);
  1554. X    return s;
  1555. X}
  1556. X
  1557. X/*
  1558. X * Duplicate a node.  (For strings, "duplicate" means crank up the
  1559. X * reference count.)
  1560. X */
  1561. XNODE *
  1562. Xdupnode(n)
  1563. XNODE *n;
  1564. X{
  1565. X    register NODE *r;
  1566. X
  1567. X    if (n->flags & TEMP) {
  1568. X        n->flags &= ~TEMP;
  1569. X        n->flags |= MALLOC;
  1570. X        return n;
  1571. X    }
  1572. X    if ((n->flags & (MALLOC|STR)) == (MALLOC|STR)) {
  1573. X        if (n->stref < 255)
  1574. X            n->stref++;
  1575. X        return n;
  1576. X    }
  1577. X    r = newnode(Node_illegal);
  1578. X    *r = *n;
  1579. X    r->flags &= ~(PERM|TEMP);
  1580. X    r->flags |= MALLOC;
  1581. X    if (n->type == Node_val && (n->flags & STR)) {
  1582. X        r->stref = 1;
  1583. X        emalloc(r->stptr, char *, r->stlen + 1, "dupnode");
  1584. X        memcpy(r->stptr, n->stptr, r->stlen+1);
  1585. X    }
  1586. X    return r;
  1587. X}
  1588. X
  1589. X/* this allocates a node with defined numbr */
  1590. XNODE *
  1591. Xmake_number(x)
  1592. XAWKNUM x;
  1593. X{
  1594. X    register NODE *r;
  1595. X
  1596. X    r = newnode(Node_val);
  1597. X    r->numbr = x;
  1598. X    r->flags |= (NUM|NUMERIC);
  1599. X    r->stref = 0;
  1600. X    return r;
  1601. X}
  1602. X
  1603. X/*
  1604. X * This creates temporary nodes.  They go away quite quickly, so don't use
  1605. X * them for anything important 
  1606. X */
  1607. XNODE *
  1608. Xtmp_number(x)
  1609. XAWKNUM x;
  1610. X{
  1611. X    NODE *r;
  1612. X
  1613. X    r = make_number(x);
  1614. X    r->flags |= TEMP;
  1615. X    return r;
  1616. X}
  1617. X
  1618. X/*
  1619. X * Make a string node.
  1620. X */
  1621. X
  1622. XNODE *
  1623. Xmake_str_node(s, len, scan)
  1624. Xchar *s;
  1625. Xint len;
  1626. Xint scan;
  1627. X{
  1628. X    register NODE *r;
  1629. X    char *pf;
  1630. X    register char *pt;
  1631. X    register int c;
  1632. X    register char *end;
  1633. X
  1634. X    r = newnode(Node_val);
  1635. X    emalloc(r->stptr, char *, len + 1, s);
  1636. X    memcpy(r->stptr, s, len);
  1637. X    r->stptr[len] = '\0';
  1638. X    end = &(r->stptr[len]);
  1639. X           
  1640. X    if (scan) {    /* scan for escape sequences */
  1641. X        for (pf = pt = r->stptr; pf < end;) {
  1642. X            c = *pf++;
  1643. X            if (c == '\\') {
  1644. X                c = parse_escape(&pf);
  1645. X                if (c < 0)
  1646. X                    cant_happen();
  1647. X                *pt++ = c;
  1648. X            } else
  1649. X                *pt++ = c;
  1650. X        }
  1651. X        len = pt - r->stptr;
  1652. X        erealloc(r->stptr, char *, len + 1, "make_str_node");
  1653. X        r->stptr[len] = '\0';
  1654. X        r->flags |= PERM;
  1655. X    }
  1656. X    r->stlen = len;
  1657. X    r->stref = 1;
  1658. X    r->flags |= (STR|MALLOC);
  1659. X
  1660. X    return r;
  1661. X}
  1662. X
  1663. X/* Read the warning under tmp_number */
  1664. XNODE *
  1665. Xtmp_string(s, len)
  1666. Xchar *s;
  1667. Xint len;
  1668. X{
  1669. X    register NODE *r;
  1670. X
  1671. X    r = make_string(s, len);
  1672. X    r->flags |= TEMP;
  1673. X    return r;
  1674. X}
  1675. X
  1676. X
  1677. X#define NODECHUNK    100
  1678. X
  1679. Xstatic NODE *nextfree = NULL;
  1680. X
  1681. XNODE *
  1682. Xnewnode(ty)
  1683. XNODETYPE ty;
  1684. X{
  1685. X    NODE *it;
  1686. X    NODE *np;
  1687. X
  1688. X#ifdef MPROF
  1689. X    emalloc(it, NODE *, sizeof(NODE), "newnode");
  1690. X#else
  1691. X    if (nextfree == NULL) {
  1692. X        /* get more nodes and initialize list */
  1693. X        emalloc(nextfree, NODE *, NODECHUNK * sizeof(NODE), "newnode");
  1694. X        for (np = nextfree; np < &nextfree[NODECHUNK - 1]; np++)
  1695. X            np->nextp = np + 1;
  1696. X        np->nextp = NULL;
  1697. X    }
  1698. X    /* get head of freelist */
  1699. X    it = nextfree;
  1700. X    nextfree = nextfree->nextp;
  1701. X#endif
  1702. X    it->type = ty;
  1703. X    it->flags = MALLOC;
  1704. X#ifdef MEMDEBUG
  1705. X    fprintf(stderr, "node: new: %0x\n", it);
  1706. X#endif
  1707. X    return it;
  1708. X}
  1709. X
  1710. Xvoid
  1711. Xfreenode(it)
  1712. XNODE *it;
  1713. X{
  1714. X#ifdef DEBUG
  1715. X    NODE *nf;
  1716. X#endif
  1717. X#ifdef MEMDEBUG
  1718. X    fprintf(stderr, "node: free: %0x\n", it);
  1719. X#endif
  1720. X#ifdef MPROF
  1721. X    free((char *) it);
  1722. X#else
  1723. X#ifdef DEBUG
  1724. X    for (nf = nextfree; nf; nf = nf->nextp)
  1725. X        if (nf == it)
  1726. X            fatal("attempt to free free node");
  1727. X#endif
  1728. X    /* add it to head of freelist */
  1729. X    it->nextp = nextfree;
  1730. X    nextfree = it;
  1731. X#endif
  1732. X}
  1733. X
  1734. X#ifdef DEBUG
  1735. Xpf()
  1736. X{
  1737. X    NODE *nf = nextfree;
  1738. X    while (nf != NULL) {
  1739. X        fprintf(stderr, "%0x ", nf);
  1740. X        nf = nf->nextp;
  1741. X    }
  1742. X}
  1743. X#endif
  1744. X
  1745. Xvoid
  1746. Xdo_deref()
  1747. X{
  1748. X    if (deref == NULL)
  1749. X        return;
  1750. X    if (deref->flags & PERM) {
  1751. X        deref = 0;
  1752. X        return;
  1753. X    }
  1754. X    if ((deref->flags & MALLOC) || (deref->flags & TEMP)) {
  1755. X        deref->flags &= ~TEMP;
  1756. X        if (deref->flags & STR) {
  1757. X            if (deref->stref > 1 && deref->stref != 255) {
  1758. X                deref->stref--;
  1759. X                deref = 0;
  1760. X                return;
  1761. X            }
  1762. X            free(deref->stptr);
  1763. X        }
  1764. X        freenode(deref);
  1765. X    }
  1766. X    deref = 0;
  1767. X}
  1768. END_OF_FILE
  1769.   if test 6310 -ne `wc -c <'./node.c'`; then
  1770.     echo shar: \"'./node.c'\" unpacked with wrong size!
  1771.   fi
  1772.   # end of './node.c'
  1773. fi
  1774. echo shar: End of archive 15 \(of 16\).
  1775. cp /dev/null ark15isdone
  1776. MISSING=""
  1777. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  1778.     if test ! -f ark${I}isdone ; then
  1779.     MISSING="${MISSING} ${I}"
  1780.     fi
  1781. done
  1782. if test "${MISSING}" = "" ; then
  1783.     echo You have unpacked all 16 archives.
  1784.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1785. else
  1786.     echo You still must unpack the following archives:
  1787.     echo "        " ${MISSING}
  1788. fi
  1789. exit 0
  1790. exit 0 # Just in case...
  1791.